<!DOCTYPE html>
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="design-patterns.css" rel="stylesheet" type="text/css">
</head>
<body>
<section id="pattern-name-list-view">
<h1>Перечень шаблонов проектирования</h1>
	
<h2>Базовые паттерны</h2>
<ul>
		
<li>Mapper
			&mdash;
			Распределитель</li>
		
<li>Money
			&mdash;
			Деньги</li>
		
<li>Special Case
			&mdash;
			Особый Случай</li>
		
<li>Plugin
			&mdash;
			Плагин</li>
		
<li>Gateway
			&mdash;
			Шлюз</li>
		
<li>Separated Interface
			&mdash;
			Выделенный интерфейс</li>
		
<li>Registry
			&mdash;
			Реестр</li>
		
<li>Service Stub
			&mdash;
			Сервисная заглушка</li>
		
<li>Value Object
			&mdash;
			Объект-значение</li>
		
<li>Record Set
			&mdash;
			Record Set</li>
		
<li>Layer Supertype
			&mdash;
			Супертип Уровня</li>
	
</ul>
	
<h2>Паттерны веб-представления</h2>
<ul>
		
<li>Transform View
			&mdash;
			Преобразователь</li>
		
<li>Template View
			&mdash;
			Шаблонизатор</li>
		
<li>Application Controller
			&mdash;
			Контроллер приложения</li>
		
<li>Two Step View
			&mdash;
			Двухшаговая шаблонизация</li>
		
<li>Page Controller
			&mdash;
			Контроллер страницы</li>
		
<li>Front Controller
			&mdash;
			Контроллер входа / Единая точка входа</li>
		
<li>MVC - Model View Controller
			&mdash;
			Модель-Вид-Контроллер</li>
	
</ul>
	
<h2>Паттерны архитектуры источников данных</h2>
<ul>
		
<li>Row Data Gateway
			&mdash;
			Шлюз к данным записи</li>
		
<li>Active Record
			&mdash;
			Активная запись</li>
		
<li>Table Data Gateway
			&mdash;
			Шлюз к данным таблицы</li>
		
<li>Data Mapper
			&mdash;
			Data Mapper</li>
	
</ul>
	
<h2>Паттерны Объектно-Реляционной логики</h2>
<ul>
		
<li>Lazy Load
			&mdash;
			Ленивая загрузка</li>
		
<li>Identity Map
			&mdash;
			Карта присутствия / Карта соответствия</li>
		
<li>Unit of Work
			&mdash;
			Единица работы</li>
	
</ul>
	
<h2>Паттерны Объектно-Реляционного структурирования</h2>
<ul>
		
<li>Identity Field
			&mdash;
			Поле первичного ключа</li>
		
<li>Foreign Key Mapping
			&mdash;
			Разметка внешних ключей</li>
		
<li>Association Table Mapping
			&mdash;
			Разметка таблиц связей</li>
		
<li>Dependent Mapping
			&mdash;
			Управление распределением подчинённых сущностей</li>
		
<li>Embedded Value
			&mdash;
			Объединённое свойство</li>
		
<li>Serialized LOB
			&mdash;
			Сериализованный LOB</li>
		
<li>Single Table Inheritance
			&mdash;
			Наследование с единой таблицей</li>
		
<li>Class Table Inheritance
			&mdash;
			Наследование с таблицами классов</li>
		
<li>Concrete Table Inheritance
			&mdash;
			Наследование с таблицами конечных классов</li>
		
<li>Inherritance Mappers
			&mdash;
			Наследуемые распределители</li>
	
</ul>
	
<h2>Паттерны логики сущности</h2>
<ul>
		
<li>Transaction Script
			&mdash;
			Сценнарий транзакции</li>
		
<li>Domain Model
			&mdash;
			Модель области определения</li>
		
<li>Table Module
			&mdash;
			Обработчик таблицы</li>
		
<li>Service Layer
			&mdash;
			Сервисный уровень</li>
	
</ul>
	
<h2>Паттерны обработки Объектно-Реляционных метаданных</h2>
<ul>
		
<li>Metadata Mapping
			&mdash;
			Распределение на основе метаданных</li>
		
<li>Query Object
			&mdash;
			Объект-запрос</li>
		
<li>Repository
			&mdash;
			Репозиторий</li>
	
</ul>
	
<h2>Паттерны распределения данных</h2>
<ul>
		
<li>Remote Facade
			&mdash;
			Парадный вход</li>
		
<li>Data Transfer Object
			&mdash;
			Объект передачи данных</li>
	
</ul>
	
<h2>Паттерны локальной конкуренции</h2>
<ul>
		
<li>Optimistic offline Lock
			&mdash;
			Оптимистичная блокировка</li>
		
<li>Pessimistic offline Lock
			&mdash;
			Пессимистичная блокировка</li>
		
<li>Coarse Grained Lock
			&mdash;
			Грубая блокировка</li>
		
<li>Implicit Lock
			&mdash;
			Скрытая блокировка</li>
	
</ul>

</section>
<section id="pattern-diagram-view">
<h1>Шаблоны проектирования в диаграммах</h1>
	
<h2>Базовые паттерны</h2>
		
<h3>Mapper
			&mdash;
			Распределитель</h3>
<img src="%0A%09%09%09%09img/mapper.gif%0A%09%09%09">
		<h3>Money
			&mdash;
			Деньги</h3>
<img src="%0A%09%09%09%09img/money.gif%0A%09%09%09">
		<h3>Special Case
			&mdash;
			Особый Случай</h3>
<img src="%0A%09%09%09%09img/special-case.gif%0A%09%09%09">
		<h3>Plugin
			&mdash;
			Плагин</h3>
<img src="%0A%09%09%09%09img/plugin.gif%0A%09%09%09">
		<h3>Gateway
			&mdash;
			Шлюз</h3>
<img src="%0A%09%09%09%09img/gateway.gif%0A%09%09%09">
		<h3>Separated Interface
			&mdash;
			Выделенный интерфейс</h3>
<img src="%0A%09%09%09%09img/separated-interface.gif%0A%09%09%09">
		<h3>Registry
			&mdash;
			Реестр</h3>
<img src="%0A%09%09%09%09img/registry.gif%0A%09%09%09">
		<h3>Service Stub
			&mdash;
			Сервисная заглушка</h3>
<img src="%0A%09%09%09%09img/service-stub.gif%0A%09%09%09">
		<h3>Value Object
			&mdash;
			Объект-значение</h3>
<img src="%0A%09%09%09%09img/value-object.gif%0A%09%09%09">
		<h3>Record Set
			&mdash;
			Record Set</h3>
<img src="%0A%09%09%09%09img/record-set.gif%0A%09%09%09">
		<h3>Layer Supertype
			&mdash;
			Супертип Уровня</h3>
<img src="%0A%09%09%09%09img/layer-supertype.gif%0A%09%09%09">
	
	<h2>Паттерны веб-представления</h2>
		
<h3>Transform View
			&mdash;
			Преобразователь</h3>
<img src="%0A%09%09%09%09img/transform-view.gif%0A%09%09%09">
		<h3>Template View
			&mdash;
			Шаблонизатор</h3>
<img src="%0A%09%09%09%09img/template-view.gif%0A%09%09%09">
		<h3>Application Controller
			&mdash;
			Контроллер приложения</h3>
<img src="%0A%09%09%09%09img/application-controller.gif%0A%09%09%09">
		<h3>Two Step View
			&mdash;
			Двухшаговая шаблонизация</h3>
<img src="%0A%09%09%09%09img/two-step-view.gif%0A%09%09%09">
		<h3>Page Controller
			&mdash;
			Контроллер страницы</h3>
<img src="%0A%09%09%09%09img/page-controller.gif%0A%09%09%09">
		<h3>Front Controller
			&mdash;
			Контроллер входа / Единая точка входа</h3>
<img src="%0A%09%09%09%09img/front-controller.gif%0A%09%09%09">
		<h3>MVC - Model View Controller
			&mdash;
			Модель-Вид-Контроллер</h3>
<img src="%0A%09%09%09%09img/mvc.gif%0A%09%09%09">
	
	<h2>Паттерны архитектуры источников данных</h2>
		
<h3>Row Data Gateway
			&mdash;
			Шлюз к данным записи</h3>
<img src="%0A%09%09%09%09img/row-data-gateway.gif%0A%09%09%09">
		<h3>Active Record
			&mdash;
			Активная запись</h3>
<img src="%0A%09%09%09%09img/active-record.gif%0A%09%09%09">
		<h3>Table Data Gateway
			&mdash;
			Шлюз к данным таблицы</h3>
<img src="%0A%09%09%09%09img/table-data-gateway.gif%0A%09%09%09">
		<h3>Data Mapper
			&mdash;
			Data Mapper</h3>
<img src="%0A%09%09%09%09img/data-mapper.gif%0A%09%09%09">
	
	<h2>Паттерны Объектно-Реляционной логики</h2>
		
<h3>Lazy Load
			&mdash;
			Ленивая загрузка</h3>
<img src="%0A%09%09%09%09img/lazy-load.gif%0A%09%09%09">
		<h3>Identity Map
			&mdash;
			Карта присутствия / Карта соответствия</h3>
<img src="%0A%09%09%09%09img/identity-map.gif%0A%09%09%09">
		<h3>Unit of Work
			&mdash;
			Единица работы</h3>
<img src="%0A%09%09%09%09img/unit-of-work.gif%0A%09%09%09">
	
	<h2>Паттерны Объектно-Реляционного структурирования</h2>
		
<h3>Identity Field
			&mdash;
			Поле первичного ключа</h3>
<img src="%0A%09%09%09%09img/identity-field.gif%0A%09%09%09">
		<h3>Foreign Key Mapping
			&mdash;
			Разметка внешних ключей</h3>
<img src="%0A%09%09%09%09img/foreign-key-mapping.gif%0A%09%09%09">
		<h3>Association Table Mapping
			&mdash;
			Разметка таблиц связей</h3>
<img src="%0A%09%09%09%09img/association-table-mapping.gif%0A%09%09%09">
		<h3>Dependent Mapping
			&mdash;
			Управление распределением подчинённых сущностей</h3>
<img src="%0A%09%09%09%09img/dependent-mapping.gif%0A%09%09%09">
		<h3>Embedded Value
			&mdash;
			Объединённое свойство</h3>
<img src="%0A%09%09%09%09img/embedded-value.gif%0A%09%09%09">
		<h3>Serialized LOB
			&mdash;
			Сериализованный LOB</h3>
<img src="%0A%09%09%09%09img/serialized-lob.gif%0A%09%09%09">
		<h3>Single Table Inheritance
			&mdash;
			Наследование с единой таблицей</h3>
<img src="%0A%09%09%09%09img/single-table-inheritance.gif%0A%09%09%09">
		<h3>Class Table Inheritance
			&mdash;
			Наследование с таблицами классов</h3>
<img src="%0A%09%09%09%09img/class-table-inheritance.gif%0A%09%09%09">
		<h3>Concrete Table Inheritance
			&mdash;
			Наследование с таблицами конечных классов</h3>
<img src="%0A%09%09%09%09img/concrete-table-inheritance.gif%0A%09%09%09">
		<h3>Inherritance Mappers
			&mdash;
			Наследуемые распределители</h3>
<img src="%0A%09%09%09%09img/inheritance-mappers.gif%0A%09%09%09">
	
	<h2>Паттерны логики сущности</h2>
		
<h3>Transaction Script
			&mdash;
			Сценнарий транзакции</h3>
<img src="%0A%09%09%09%09img/transaction-script.gif%0A%09%09%09">
		<h3>Domain Model
			&mdash;
			Модель области определения</h3>
<img src="%0A%09%09%09%09img/domain-model.gif%0A%09%09%09">
		<h3>Table Module
			&mdash;
			Обработчик таблицы</h3>
<img src="%0A%09%09%09%09img/table-module.gif%0A%09%09%09">
		<h3>Service Layer
			&mdash;
			Сервисный уровень</h3>
<img src="%0A%09%09%09%09img/service-layer.gif%0A%09%09%09">
	
	<h2>Паттерны обработки Объектно-Реляционных метаданных</h2>
		
<h3>Metadata Mapping
			&mdash;
			Распределение на основе метаданных</h3>
<img src="%0A%09%09%09%09img/metadata-mapping.gif%0A%09%09%09">
		<h3>Query Object
			&mdash;
			Объект-запрос</h3>
<img src="%0A%09%09%09%09img/query-object.gif%0A%09%09%09">
		<h3>Repository
			&mdash;
			Репозиторий</h3>
<img src="%0A%09%09%09%09img/repository.gif%0A%09%09%09">
	
	<h2>Паттерны распределения данных</h2>
		
<h3>Remote Facade
			&mdash;
			Парадный вход</h3>
<img src="%0A%09%09%09%09img/remote-facade.gif%0A%09%09%09">
		<h3>Data Transfer Object
			&mdash;
			Объект передачи данных</h3>
<img src="%0A%09%09%09%09img/data-transfer-object.gif%0A%09%09%09">
	
	<h2>Паттерны локальной конкуренции</h2>
		
<h3>Optimistic offline Lock
			&mdash;
			Оптимистичная блокировка</h3>
<img src="%0A%09%09%09%09img/optimistic-offline-lock.gif%0A%09%09%09">
		<h3>Pessimistic offline Lock
			&mdash;
			Пессимистичная блокировка</h3>
<img src="%0A%09%09%09%09img/pessimistic-offline-lock.gif%0A%09%09%09">
		<h3>Coarse Grained Lock
			&mdash;
			Грубая блокировка</h3>
<img src="%0A%09%09%09%09img/coarse-grained-lock.gif%0A%09%09%09">
		<h3>Implicit Lock
			&mdash;
			Скрытая блокировка</h3>
<img src="%0A%09%09%09%09img/implicit-lock.gif%0A%09%09%09">
	
</section>
<section id="full-view">
<h1>Шаблоны проектирования с описанием</h1>
	
<h2>Базовые паттерны</h2>
		
<h3>Mapper
			&mdash;
			Распределитель</h3>
<img src="%0A%09%09%09%09img/mapper.gif%0A%09%09%09"><p>
<desc>
				
<p>Объект, который управляет сообщением между независимыми друг от
					друга объектами.
				</p>

				
<p>Иногда нужно установить сообщение между двумя подсистемами,
					который, между тем должны оставаться в неведении друг о друге. Это
					может быть обусловлено невозможностью изменения этих объектов, или
					просто нежеланием создавать зависимости между ними или между ними и
					изолирующей частью.
				</p>
			
</desc>
</p>
		
<h3>Money
			&mdash;
			Деньги</h3>
<img src="%0A%09%09%09%09img/money.gif%0A%09%09%09"><p>
<desc>
				
<p>
					Огромное количество компьютеров в мире обрабатывают данные о
					деньгах.
					Удивительно, что класс Деньги до сих пор не является
					базовым в
					любом языке программирования. Недостаток такого рода типа
					данных
					приводит к проблемам, наиболее заметные из которых - работа с
					валютой. Если все вычисления в программе проделываются в одной
					валюте, никаких особых проблем нет, но как только вводится
					многовалютность - надо думать о том, чтобы не сложить 10 долларов с
					10 йенами без перевода курсов валют. Менее заметна проблема с
					округлением. Денежные вычисления часто округляют до наименьшей из
					существующих мер. При этом легко не учесть копейки из-за ошибок
					округления.
				</p>
				
<p>
					Что действительно хорошо в ООП, так это то, что вы можете
					исправить
					эти проблемы, созданием класса Money (Деньги), чтобы
					работать с
					денежными величинами и избегать общих ошибок.
				</p>
			
</desc>
</p>
		
<h3>Special Case
			&mdash;
			Особый Случай</h3>
<img src="%0A%09%09%09%09img/special-case.gif%0A%09%09%09"><p>
<desc>
				
<p>
					Подкласс, содержащий особую логику для отдельных ситуаций.
				</p>
				
<p>
					Null-значения в ООП - неуклюжая вещь, так как она зарубает на
					корню полиморфизм.
					Обычно есть возможность вызова какого-либо метода
					на переменной
					заданного типа без необходимости беспокоиться о том,
					принадлежит ли
					эта переменная конкретному классу или подклассу. В
					строго
					типизированных языках эту проверку делает компилятор. Тем не
					менее,
					из-за того, что переменная может содержать null, существует
					опасность возникновения ошибки во время выполнения, при вызове
					метода на null-значении.
				</p>
				
<p>
					Если переменная может принимать значение null, вам нужно
					постоянно
					заботиться о проверках на null и правильной обработке
					null-значений. Часто, эта "правильная обработка" одинакова во
					большинстве случаев, и всё это заканчивается совершением греха
					дублированием кода (дословный перевод Мартина Фаулера).
				</p>
				
<p>
					Null-значения - яркий пример таких проблем, которые возникают
					постоянно и
					внезапно. А их много. Например, во многих системах
					приходится
					работать с бесконечностью, которая имеет особые правила
					для,
					например, сложения и нарушает обычные аксиомы, справедливые для
					натуральных чисел. Такие случаи предполагают изменение обычного
					поведения типа.
				</p>
				
<p>
					Вместо того, чтобы возвращать null или какое-то дополнительное
					значение,
					верните Special Case (Особый Случай) - объект с тем же
					интерфейсом,
					но ведущий себя иначе, чем основной.
				</p>
			
</desc>
</p>
		
<h3>Plugin
			&mdash;
			Плагин</h3>
<img src="%0A%09%09%09%09img/plugin.gif%0A%09%09%09"><p>
<desc>
				
<p>
					Соединяет классы во время конфигурации, а не компиляции.
				</p>
				
<p>
					Паттерн Separated Interface (Выделенный интерфейс) часто
					используется,
					когда один код выполняется в нескольких средах и
					требует разной
					реализации отдельной логики. Большинство
					разработчиков добиваются
					этого при помощи использования шаблона
					фабрики. Представим, что
					надо генерировать первичный ключ при помощи
					паттерна Separated
					Interface (Выделенный интерфейс). Можно
					использовать для
					юнит-тестирования простой объект-счёчик, а на
					реальной системе -
					последовательность из БД. Фабричный метод скорее
					всего будет
					содержать условный переход (if), проверяющий, установлен
					ли флаг
					тестирования, и возвращать необходимый генератор ключа.
				</p>
				
<p>Как только у вас появится ещё несколько фабрик - начнётся
					путаница. Создание новой конфигурации, например "запуск юнит-тестов
					на БД без контроля транзакций" или "запуск в продакшн на DB2 с
					полной поддержкой транзакций", потребует правок в условиях в
					большом количестве фабрик, пересборку и переразвёртывание.
				</p>
				
<p>
					Конфигурация не должна быть разбросана по приложению, также как и
					требовать
					пересборки и переразвёртывания. Паттерн Plugin решает обе
					эти
					проблемы, предоставляя централизованную динамическую
					конфигурацию.
				</p>
			
</desc>
</p>
		
<h3>Gateway
			&mdash;
			Шлюз</h3>
<img src="%0A%09%09%09%09img/gateway.gif%0A%09%09%09"><p>
<desc>
				
<p> Объект, который инкапсулирует доступ к внешней системе и
					ресурсу.
				</p>
				
<p>
					Достойное ПО редко функционирует в изоляции от внешнего мира.
					Даже самая
					строго объектно-ориентированная система часто вынуждена
					взаимодействовать с "не объектами", например реляционная БД, CICS
					транзакции или структурами XML.
				</p>
				
<p>
					При доступе к такого рода внешним ресурсам, обычно используется
					API.
					Однако, API изначально являются чем-то сложным, потому что
					принимают во внимание структуру ресурса. Каждый, кто хочет понять
					какой-нибудь ресурс, должен понять его API - будь то JDBC и SQL для
					реляционных БД или W3C или JDOM для XML. Это делает ПО не только
					менее понятным, но ещё это делает изменения гораздо более сложными,
					например, если вы собираетесь перейти со временем с SQL на XML.
				</p>
				
<p>
					Решением здесь является обёртывание всего специального API в
					класс,
					интерфейс которого выглядит как интерфейс обычного объекта.
					Остальные объекты обращаются к ресурсу через этот Шлюз, который
					транслирует эти простые вызовы в соответствующий специальный
					API-код
				</p>
			
</desc>
</p>
		
<h3>Separated Interface
			&mdash;
			Выделенный интерфейс</h3>
<img src="%0A%09%09%09%09img/separated-interface.gif%0A%09%09%09"><p>
<desc>

				
<p>
					Выделение какого-либо интерфейса к объекту в отдельный от объекта
					пакет
				</p>
				
<p>
					При разработке какой-либо системы, можно добиться улучшение её
					архитектуры, уменьшая связанность между её частями. Это можно
					сделать так - распределив классы по отдельным пакетам и
					контролировать зависимости этими пакетами. Тогда можно следовать
					правилам о том, как классы из одного пакета могут обращаться к
					классам из другого пакета. Например, то, которое запрещает классам
					с уровня данных обращаться к классам с уровня представления.
				</p>
				
<p>
					Тем не менее, может возникнуть необходимость реализовать методы,
					которые противоречат основной структуре зависимостей. В таком
					случае можно использовать Выделенный Интерфейс, чтобы определить
					какой-либо интерфейс в одном пакете, а реализовать в другом. Таким
					образом, любой клиент, которому нужна зависимость от этого
					интерфейса может совершенно не думать о реализации доступа. Паттерн
					Separated Interface (Выделенный Интерфейс) предоставляет хорошую
					точку подключения паттерна Gateway (Шлюз)
				</p>
			
</desc>
</p>
		
<h3>Registry
			&mdash;
			Реестр</h3>
<img src="%0A%09%09%09%09img/registry.gif%0A%09%09%09"><p>
<desc>
				
<p>
					Хорошо известный объект, который используется другими объектами для
					получения общих объектов и сервисов.
				</p>
				
<p>
					Когда нужно найти какой-нибудь объект, обычно начинают с другого
					объекта,
					связанного с целевым. Например, если нужно найти все счета для
					покупателя, начинают, как раз с покупателя и используют его метод
					получения счетов. Тем не менее, в некоторых случаях нет подходящего
					объекта, с которого начать. Например, известен ID покупателя, но нет
					ссылки на него. Тогда нужен своего рода объект-поисковик, но тогда
					возникает вопрос - как вы найдёте сам поисковик?
				</p>
				
<p>
					Реестр (Registry) - это глобальный объект по сути своей или, по крайней
					мере, так выглядит - он может функционировать только будучи
					глобальным.
				</p>
			
</desc>
</p>
		
<h3>Service Stub
			&mdash;
			Сервисная заглушка</h3>
<img src="%0A%09%09%09%09img/service-stub.gif%0A%09%09%09"><p>
<desc>
				
<p>
					Ликвидирует зависимость от внешних проблемных сервисов во время тестирования.
				</p>
				
<p>
					Enterprise-системы часто зависят от внешних сервисов, таких как,
					например, расчёт кредитного рейтинга, ставки налогов и т.п. Любой
					разработчик, который когда-либо имел дело с такими системами
					пожалуется на лишнюю зависимость от абсолютно неконтролируемого
					ресурса. Часто эти сервисы не блещут стабильностью и надёжностью.
				</p>
				
<p>
					В итоге, эти проблемы могут замедлять разработку. Разработчики
					вынуждены сидеть и ждать, когда удалённый сервис возобновит свою
					работу или встраивать в код &laquo;костыли&raquo;, чтобы обходить зависимость
					от
					сервиса. Ещё хуже, когда не получается выполнять тесты - весь
					процесс разработки нарушается.
				</p>
				
<p>
					Замена сервиса на заглушку (Service Stub), которая выполняется локально и
					быстро, улучшит разработку.
				</p>
			
</desc>
</p>
		
<h3>Value Object
			&mdash;
			Объект-значение</h3>
<img src="%0A%09%09%09%09img/value-object.gif%0A%09%09%09"><p>
<desc>
				
<p>Маленький объект для хранения величин таких как деньги или
					диапазон дат, равенство которых не основано на идентичности.
				</p>
				
<p>
					При работе с ООП, приходишь к выводу, что полезно разделять ссылочные
					объекты и объекты-значения. Объект-значение обычно гораздо меньше.
					Он как простой тип данных из тех языков, которые не являются
					полностью объектно-ориентированными.
				</p>
			
</desc>
</p>
		
<h3>Record Set
			&mdash;
			Record Set</h3>
<img src="%0A%09%09%09%09img/record-set.gif%0A%09%09%09"><p>
<desc>
				
<p>Представление данных из таблицы в приложении.
				</p>
				
<p>
					За последние двадцать лет основным способом представления данных в БД
					стали реляционные таблицы. Почти каждый новый разработчик
					использует
					реляционные данные.
				</p>
				
<p>
					На этой почве появилось множество инструментов для быстрого
					построения
					UI (пользовательского интерфейса). Эти UI-фреймворки основываются на
					реляционности данных и предоставляют различные UI-элементы, которые
					легко настраиваются и управляются практически безо всякого
					программирования.
				</p>
				
<p>
					Обратная сторона медали в том, что, несмотря на невероятную лёгкость вывода
					и работы с данными, эти элементы не предусматривают возможности
					добавления кода бизнес-логики. Проверки типа "правильный ли формат
					у
					эта даты" и любые правила исполнения попросту некуда поставить. И в
					итоге, эта логика либо забивается в БД, либо смешивается в кодом
					вывода информации.
				</p>
				
<p>
					Суть Record Set в предоставлении структуры данных, которая выглядит в
					точности как результат SQL-запроса, но может управляться и
					обрабатываться любыми частями системы.
				</p>
			
</desc>
</p>
		
<h3>Layer Supertype
			&mdash;
			Супертип Уровня</h3>
<img src="%0A%09%09%09%09img/layer-supertype.gif%0A%09%09%09"><p>
<desc>
				
<p>Тип, выступающий родительским для всех типов в своём уровне
				</p>
				
<p>
					Нередко все классы одного уровня имеют одинаковые методы, которые не
					хочется дублировать повсеместно. Для того, чтобы избежать
					дублирования, можно все общие методы перенести в один класс (Layer
					Supertype), который будет являться Супертипом (читай - родителем)
					всех классов в своём уровне.
				</p>
			
</desc>
</p>
	
	
<h2>Паттерны веб-представления</h2>
		
<h3>Transform View
			&mdash;
			Преобразователь</h3>
<img src="%0A%09%09%09%09img/transform-view.gif%0A%09%09%09"><p>
<desc>
				
<p>Преобразует записи в HTML по одной.
				</p>
				
<p>
					Когда выполняются запросы к БД, вы получаете данные, но этого не
					достаточно, чтобы отобразить нормальную web-страницу. Задача вида
					(view) в паттерне MVC - Model View Controller - формировать данные
					в
					web-страницу. Использование Transform View подразумевает
					преобразование, когда на входе есть модель, а на выходе HTML.
				</p>
				
<p>
					Пример: на входе преобразователя модель, содержащая имя альбома
					(album name) и имя артиста (artist name). На выходе - код &lt;a
					href="http://exapmle.com/music/album_name/artist_name"&gt; artist
					name &lt;/a&gt; </p>
			
</desc>
</p>
		
<h3>Template View
			&mdash;
			Шаблонизатор</h3>
<img src="%0A%09%09%09%09img/template-view.gif%0A%09%09%09"><p>
<desc>
				
<p>Заполняет HTML-шаблон информацией при помощи маркеров,
					указанных в шаблоне.
				</p>
				
<p>
					Создание приложений, генерирующих HTML, зачастую гораздо более сложно, чем
					кажется. Несмотря на то, что современные языки программирования
					стали лучше справляться с обработкой текста, создание, и
					конкатенация строк всё ещё представляется проблемой. Если надо
					выводить немного информации - это не так страшно, но если надо
					сгенерировать целую HTML-страницу - появляется много работы с
					текстом.
				</p>
				
<p>
					В случае со статическими HTML-страницами, которые не меняются от
					запроса к запросу, можно использоваться удобный WYSIWYG-редактор.
					Даже те, кто любят обычные текстовые редакторы согласятся, что
					набирать текст и тэги проще и удобнее, чем собирать их через
					конкатенации в языке программирования.
				</p>
				
<p>
					Конечно, возникает проблема в случае с динамическими страницами, которые,
					например, берут данные из БД и наполняют ими HTML. Страницы
					выглядят
					по-разному каждый раз, и использование обычного HTML-редактора не
					подходит.
				</p>
				
<p>
					Наилучший выход из положения - создание динамических страниц так же, как и
					статических, но помечая их маркерами, которые могут быть заменены
					динамической информацией.
				</p>
				
<p>
					Пример: при обработке шаблона, области, помеченные специальными маркерами
					(на иллюстрации - тегами &lt;jsp:.../&gt;) заменяются результатами
					вызовов методов helper'a.
				</p>
			
</desc>
</p>
		
<h3>Application Controller
			&mdash;
			Контроллер приложения</h3>
<img src="%0A%09%09%09%09img/application-controller.gif%0A%09%09%09"><p>
<desc>
				
<p>Единая точка управления отображением и выполнением приложения.
				</p>
				
<p>
					Некоторые приложения содержат в разных своих частях значительное
					количество кода, управляющего отображением, и который может влиять
					на некоторые отображения в некоторых условиях. Конечно, есть
					пошаговый тип взаимодействия, когда пользователь последовательно
					проходит через страницы (экраны) в строго определённом порядке. В
					остальных же случаях могут быть страницы, появляющиеся только в
					определённых условиях или выбор следующего отображения зависит от
					того, что ввёл пользователь ранее.
				</p>
				
<p>
					В некотором роде, различные контроллеры в паттерне MVC могут делать
					этот выбор, однако с ростом приложения это выльется в дублирование
					кода, так как несколько контроллеров должны будут знать, что делать
					в той или иной ситуации.
				</p>
				
<p>
					Устранить это дублирование можно посредством помещения всей логики
					выполнения
					приложения в Контроллер приложения (Application Controller). Тогда
					контроллер входа (Input Controller) будет обращаться к контроллеру
					приложения (Application Controller) за необходимыми к выполнению на
					модели и за необходимыми представлениями (view) в зависимости от
					контекста.

				</p>
			
</desc>
</p>
		
<h3>Two Step View
			&mdash;
			Двухшаговая шаблонизация</h3>
<img src="%0A%09%09%09%09img/two-step-view.gif%0A%09%09%09"><p>
<desc>
				
<p>Преобразует данные в HTML в два шага: сначала формирует
					логическую структуру, а позже - заполняет её отформатированными
					данными
				</p>
				
<p>
					Если web-приложение состоит из множества страниц, необходим единый вид
					и
					единая структура сайта. Если каждая страница выглядит по своему,
					получится сайт, который будет непонятным для пользователя. Также
					возможна ситуация, когда нужно сделать глобальные изменения на всём
					сайте (например поменять заголовок), но при использовании Template
					View или Transform View возникают трудности, потому что код
					представления дублируется от страницы к странице и надо исправлять
					его во всех файлах.
				</p>
				
<p>
					Шаблон Two Step View решает эту проблему разбиением шаблонизации на две
					части. В первой, данные из модели преобразуются в логическое
					представление без какого-либо другого, специфического
					форматирования. Второй шаг преобразует это логическое представление
					с использование необходимого конкретного форматирования. Таким
					образом, можно делать глобальные изменения, изменяя только второй
					шаг. Также можно сделать несколько представлений для одной и той же
					информации, выбирая на лету форматирование для второго шага.
				</p>
				
<p>
					Пример: хорошая реализация двухшаговой шаблонизации есть в фреймфорке Zend
					Framework в классе Zend_Layout. Общая оплётка отделяется от
					конкретного вида посредством layout'а.
				</p>
			
</desc>
</p>
		
<h3>Page Controller
			&mdash;
			Контроллер страницы</h3>
<img src="%0A%09%09%09%09img/page-controller.gif%0A%09%09%09"><p>
<desc>
				
<p>Объект, обрабатывающий запрос к отдельной странице или
					действию.
				</p>
				
<p>
					Большинство людей получают первый опыт в веб-программировании на статичных
					HTML-страницах. Когда происходит запрос к статической
					HTML-странице,
					веб-серверу передаётся имя и путь к хранящемуся на нём
					HTML-документу. Главная идея здесь в том, что каждая страница на
					веб-сайте является отдельным документом, хранящимся на сервере. В
					случае с динамическими страницами всё гораздо сложнее, так как
					сложнее связь между введённым адресом и отображённой страницей. Тем
					не менее, подход, когда один путь соответствует одному файлу,
					который обрабатывает запрос достаточно очевиден и прост для
					понимания.
				</p>
				
<p>
					В результате контроллер страницы (Page Controller) - паттерн, в
					котором один контроллер отвечает за отображение одной логической
					страницы. Это может быть как отдельная страница, хранящаяся на
					веб-сервере, так и отдельный объект, который отвечает за страницу.
				</p>
			
</desc>
</p>
		
<h3>Front Controller
			&mdash;
			Контроллер входа / Единая точка входа</h3>
<img src="%0A%09%09%09%09img/front-controller.gif%0A%09%09%09"><p>
<desc>
				
<p>Один контроллер обрабатывает все запросы к веб-сайту.
				</p>
				
<p>
					В сложных веб-сайтах есть много одинаковых действий, которые надо
					производить во время обработки запросов. Это, например, контроль
					безопасности, многоязычность и настройка интерфейса пользователя.
					Когда поведение входного контроллера разбросано между несколькими
					объектами, дублируется большое количество кода. Помимо прочего
					возникают сложности смены поведения в реальном времени.
				</p>
				
<p>
					Паттерн Front Controller объединяет всю обработку запросов, пропуская
					запросы через единственный объект-обработчик. Этот объект содержит
					общую логику поведения, которая может быть изменена в реальном
					времени при помощи декораторов. После обработки запроса контроллер
					обращается к конкретному объекту для отработки конкретного
					поведения.

				</p>
			
</desc>
</p>
		
<h3>MVC - Model View Controller
			&mdash;
			Модель-Вид-Контроллер</h3>
<img src="%0A%09%09%09%09img/mvc.gif%0A%09%09%09"><p>
<desc>
				
<p>Этот шаблон разделяет работу веб-приложения на три отдельные
					функциональные роли: модель данных (model), пользовательский
					интерфейс (view) и управляющую логику (controller). Таким образом,
					изменения, вносимые в один из компонентов, оказывают минимально
					возможное воздействие на другие компоненты.
				</p>
				
<p>
					В данном паттерне модель не зависит от представления или управляющей
					логики, что делает возможным проектирование модели как независимого
					компонента и, например, создавать несколько представлений для одной
					модели.
				</p>
				
<p>
					Впервые этот шаблон был применён в фреймворке, разрабатываемом для языка
					Smalltalk в конце 1970-х годов. С этого момента он играет
					основополагающую роль в большинстве фреймфорков с пользовательским
					интерфейсом. Он в корне изменил взгляд на проектирование
					приложений.
				</p>
				
<p>
					Большинство фреймворков для веб-программирования сейчас в основе
					своей содержат именно MVC. К наиболее удачным примерам применения
					этого паттерна для языка PHP можно отнести Zend Framework и cakePHP

				</p>
			
</desc>
</p>
	
	
<h2>Паттерны архитектуры источников данных</h2>
		
<h3>Row Data Gateway
			&mdash;
			Шлюз к данным записи</h3>
<img src="%0A%09%09%09%09img/row-data-gateway.gif%0A%09%09%09"><p>
<desc>
				
<p>Объект выступает в роли шлюза к отдельной записи в источнике
					данных. Один экземпляр на одну запись.
				</p>
				
<p>
					Встраивание кода доступа к БД в объекты, хранящиеся в памяти, может привести в
					некоторым неудобствам. Во-первых, если ваши объекты содержат
					бизнес-логику, добавление взаимодействия с БД увеличит сложность.
					Вскоре тестирование станет неудобным, если объекты, хранящиеся в
					памяти, завязаны на БД. Тесты станут медленнее из-за доступа к БД.
				</p>
				
<p>
					Объект шлюза к записи представляется в точности, как запись в БД, но
					при этом даёт возможность доступа посредством штатных средств языка
					программирования. Все подробности доступа к БД скрыты за этим
					интерфейсом.
				</p>
				
<p>
					Пример: объект шлюза PersonGateway, данные о записи из таблицы person и
					методы insert и update, которые позволяют прозрачно работать с
					записью.
				</p>
				
<p>
					Качественная реализация этого паттерна на PHP существует в частности в Zend
					Framework в классе Zend_Db_Table_Row

				</p>
			
</desc>
</p>
		
<h3>Active Record
			&mdash;
			Активная запись</h3>
<img src="%0A%09%09%09%09img/active-record.gif%0A%09%09%09"><p>
<desc>
				
<p>Один объект управляет и данными, и поведением. Большинство этих
					данных постоянны и их надо хранить в БД. Этот паттерн использует
					наиболее очевидный подход - хранение логики доступа к данным в
					объекте сущности.
				</p>
				
<p>
					Объект является "обёрткой" одной строки из БД или представления, включает
					в себя доступ к БД и логику обращения с данными.
				</p>
				
<p>
					Пример: объект "Работник" содержит данные об одном работнике и методы:
					добавить, обновить или удалить. Помимо прочего, отдельным методом
					вынесена смена имени.

				</p>
			
</desc>
</p>
		
<h3>Table Data Gateway
			&mdash;
			Шлюз к данным таблицы</h3>
<img src="%0A%09%09%09%09img/table-data-gateway.gif%0A%09%09%09"><p>
<desc>
				
<p>Объект выступает в качестве шлюза между данными в приложении и
					в БД. Один объект работает сразу со всеми записями в таблице.
				</p>
				
<p>
					Сочетание SQL-запросов и логики приложения может вызвать достаточно
					много проблем. Есть разработчики, которые не сильны в SQL, а есть и
					те, кто в этом преуспел. Администраторы SQL-серверов должны иметь
					возможность быстро найти SQL-код, чтобы понимать каким образом
					настраивать и развивать сервера.
				</p>
				
<p>
					Объект шлюза к таблице содержит все запросы SQL для доступа к отдельной
					таблице или представлению (view): выборка, обновление, вставка,
					удаление (CRUD). Остальной код, для взаимодействия с БД, обращается
					к методам объекта шлюза.
				</p>
				
<p>
					Пример: объект шлюза PersonGateway содержит методы для доступа к таблице
					person в БД. Методы содержат SQL-код для выборки, вставки,
					обновления и удаления. Объект может содержать специальную выборку,
					например поиск по компании.

				</p>
			
</desc>
</p>
		
<h3>Data Mapper
			&mdash;
			Data Mapper</h3>
<img src="%0A%09%09%09%09img/data-mapper.gif%0A%09%09%09"><p>
<desc>
				
<p>Объектные и реляционные БД используют разные способы
					структурирования данных. Множество составляющих объектов, например
					коллекции и наследование, не представлены в реляционных БД. Когда
					проектируется объектная модель с большим количеством бизнес-логики,
					полезно применять такие механизмы для улучшения организации
					хранения
					данных и логики, которая работает c ними. Это приводит к различиям в
					организации. Так что объектная и реляционная схемы не идентичны.
				</p>
				
<p>
					Тем не менее, необходимость в обмене данными между двумя схемами не
					отпадает, и этот обмен становится, в свою очередь, сложным. Если же
					объект знает о реляционной структуре &mdash; изменения в одной из
					структур
					приведёт к проблемам в другой.
				</p>
				
<p>
					Data Mapper &mdash; это программная прослойка, разделяющая объект и БД. Его
					обязанность &mdash; пересылать данные между ними и изолировать их друг от
					друга. При использовании Data Mapper'а объекты не нуждаются в
					знании
					о существовании БД. Они не нуждаются в SQL-коде, и (естественно) в
					информации о структуре БД. Так как Data Mapper - это разновидность
					паттерна Mapper, сам объект-Mapper неизвестен объекту.
				</p>
			
</desc>
</p>
	
	
<h2>Паттерны Объектно-Реляционной логики</h2>
		
<h3>Lazy Load
			&mdash;
			Ленивая загрузка</h3>
<img src="%0A%09%09%09%09img/lazy-load.gif%0A%09%09%09"><p>
<desc>
				
<p>бъект, не содержит данных, но знает, где их взять.
				</p>
				
<p>
					Для загрузки данных из БД в память приложения удобно пользоваться
					загрузкой не только данных об объекте, но и о сопряжённых с ним
					объектах. Это делает загрузку данных проще для разработчика: он
					просто использует объект, который, тем не менее вынужден загружать
					все данные в явном виде.
				</p>
				
<p>
					Но это ведёт к случаям, когда будет загружаться огромное количество
					сопряжённых объектов, что плохо скажется на производительности в
					случаях, когда эти данные реально не нужны.
				</p>
				
<p>
					Паттерн Lazy Load (Ленивая Загрузка) подразумевает отказ от загрузки
					дополнительных данных, когда в этом нет необходимости. Вместо этого
					ставится маркер о том, что данные не загружены и их надо загрузить
					в
					случае, если они понадобятся. Как известно, если Вы ленивы, то вы
					выигрываете в том случае, если дело, которое вы не делали на самом
					деле и не надо было делать.
				</p>
				
<p>
					Существует четыре основных варианта ленивой загрузки.
					<ul>
						
<li>Lazy Initialization (Ленивая Инициализация) использует
							специальный макер
							(обычно null), чтобы пометить поле, как не загруженное. При каждом
							обращении к полю проверяется значение маркера и, если значение
							поля
							не загружено - оно загружается.
						</li>
						
<li>
							Virtual Proxy (Виртуальный Прокси) - объект с таким же интерфейсом, как
							и
							настоящий объект. При первом обращении к методу объекта, виртуальный
							прокси загружает настоящий объект и перенаправляет выполнение.
						</li>
						
<li>
							Value Holder (Контейнер значения) - объект с методом getValue. Клиент
							вызывает метод getValue, чтобы получить реальный объект. getValue
							вызывает загрузку.
						</li>
						
<li>
							Ghost (Призрак) - объект без каких-либо данных. При первом обращении к
							его методу, призрак загружает все данные сразу.
						</li>
					
</ul>
				
</p>
			
</desc>
</p>
		
<h3>Identity Map
			&mdash;
			Карта присутствия / Карта соответствия</h3>
<img src="%0A%09%09%09%09img/identity-map.gif%0A%09%09%09"><p>
<desc>
				
<p>Обеспечивает однократную загрузку объекта, сохраняя данные об
					объекте в карте соответсвия. При обращении к объектам, ищет их в
					карте соответсвия.
				</p>
				
<p>
					Одна старая пословица постулирует, что человек с двумя часами никогда
					не
					знает, сколько сейчас времени. И если уж двое часов вносят путаницу,
					то с загрузкой объектов из БД может получиться гораздо большая
					путаница. Если разработчик не достаточно аккуратен, может
					получиться, что он загрузит данные из БД в два объекта. Потом,
					когда
					он сохранит их, получится путаница и конкуренция различных данных.
				</p>
				
<p>
					Более того, с этим связаны проблемы производительности. Когда дважды
					загружается одна и та же информация, увеличиваются затраты на
					передачу данных. Таким образом, загрузка одних и тех же данных
					дважды не только обеспечивает корректность информации, но и
					ускоряет
					работу приложения.
				</p>
				
<p>
					Паттерн Identity Map (Карта присутствия / Карта соответствия) хранит
					записи
					о всех объектах, которые были считаны из БД за время выполнения
					одного действия. Когда происходит обращение к объекту, проверяется
					карта соответствия (присутствия), чтобы узнать, загружен ли объект.
				</p>
			
</desc>
</p>
		
<h3>Unit of Work
			&mdash;
			Единица работы</h3>
<img src="%0A%09%09%09%09img/unit-of-work.gif%0A%09%09%09"><p>
<desc>
				
<p>Обслуживает набор объектов, изменяемых в бизнес-транзакции
					(бизнес-действии) и управляет записью изменений и разрешением
					проблем конкуренции данных.
				</p>
				
<p>
					Когда необходимо писать и читать из БД, важно следить за тем, что вы
					изменили и если не изменили - не записывать данные в БД. Также
					необходимо вставлять данные о новых объектах и удалять данные о
					старых.
				</p>
				
<p>
					Можно записывать в БД каждое изменение объекта, но это приведёт к
					большому количеству мелких запросов к БД, что закончится
					замедлением
					работы приложения. Более того, это требует держать открытую
					транзакцию всё время работы приложения, что непрактично, если
					приложение обрабатывает несколько запросов одновременно. Ситуация
					ещё хуже, если необходимо следить за чтением из и БД, чтобы избежать
					неконсистентного чтения.
				</p>
				
<p>
					Реализация паттерна Unit of Work следит за всеми действиями приложения,
					которые могут изменить БД в рамках одного бизнес-действия. Когда
					бизнес-действие завершается, Unit of Work выявляет все изменения и
					вносит их в БД.

				</p>
			
</desc>
</p>
	
	
<h2>Паттерны Объектно-Реляционного структурирования</h2>
		
<h3>Identity Field
			&mdash;
			Поле первичного ключа</h3>
<img src="%0A%09%09%09%09img/identity-field.gif%0A%09%09%09"><p>
<desc>
				
<p>Хранит первичный ключ из БД в объекте, чтобы обеспечивать
					соответствие между объектом и строкой в БД.
				</p>
				
<p>
					Реляционные базы данных отличают одну запись от другой при помощи первичного
					ключа. Но объекты в памяти не нуждаются в таком ключе, так как
					объектная система следит отличием объектов сама. При чтении из БД
					проблем не возникает, но для записи, нужна привязка объектной
					системы к БД.
				</p>
				
<p>
					Для этого нет ничего проще и очевиднее, чем Identity Field. Всё, что
					нужно - это хранить первичный ключ из БД в свостве объекта
				</p>
			
</desc>
</p>
		
<h3>Foreign Key Mapping
			&mdash;
			Разметка внешних ключей</h3>
<img src="%0A%09%09%09%09img/foreign-key-mapping.gif%0A%09%09%09"><p>
<desc>
				
<p>Представляет отношения по внешним ключам между таблицами в виде
					отношений между объектами
				</p>
				
<p>
					Объекты могут ссылаться друг на друга напрямую, через объектные ссылки.
					Даже простейшая объектно-ориентированная система будет содержать
					ряд
					объектов, объединённых между собой всем многообразием способов.
					Чтобы хранить эти объекты в БД, необходимо сохранять эти ссылки. Тем
					не менее, так как в разное время в объектах хранятся разные данные,
					нельзя сохранять значения "как есть". Еще больше усложняется всё
					тем, что объекты могут легко содержать коллекции ссылок на други
					объекты. Такая структура нарушает нормализацию реляционных БД.
				</p>
				
<p>
					Разметка внешних ключей сводит ссылку на объект к внешнему ключу в
					БД.
				</p>
			
</desc>
</p>
		
<h3>Association Table Mapping
			&mdash;
			Разметка таблиц связей</h3>
<img src="%0A%09%09%09%09img/association-table-mapping.gif%0A%09%09%09"><p>
<desc>
				
<p>Сохраняет соответствие в виде таблицы с внешними ключами к
					таблицам, которые объединены этим соответствием.
				</p>
				
<p>
					Объекты с лёгкостью могут управлять наборами из нескольких значений при
					использовании коллекций в качестве собственных свойств. Реляционные
					базы данных не предоставляют такой возможности и ограничиваются
					полями с одним значением. При разметке соответствия "один ко
					многим", можно использовать паттерн Foreign Key Mapping (Разметка
					внешних ключей), используя внешний ключ для однозначного
					соответствия. Но отношения "многие ко многим" не могут обеспечить
					этого, потому что нет однозначной сущности на которую ссылался бы
					внешний ключ.
				</p>
				
<p>
					Решением здесь является классическое разрешение, используемое в реляционных
					БД годами: создание дополнительной таблицы, для хранения
					множественных связей. Тогда использование Association Table Mapping
					позволит разметить многозначные поля через связующую таблицу
				</p>
			
</desc>
</p>
		
<h3>Dependent Mapping
			&mdash;
			Управление распределением подчинённых сущностей</h3>
<img src="%0A%09%09%09%09img/dependent-mapping.gif%0A%09%09%09"><p>
<desc>
				
<p>Один класс предоставляет mapping (распределение) и для
					основного класса и для зависимого.
				</p>
				
<p>
					Некоторые объекты существуют только в контексте других объектов. Песни из
					альбома могут быть загружены или сохранены в любой момент, когда
					альбом загружен или сохранён. Если они не используются другими
					таблицами в БД, то можно упростить процесс маппинга, переложив
					маппинг песен на объект-маппер альбомов. Такое поведение называется
					Dependent Mapping (Управление распределением подчинённых сущностей)
				</p>
			
</desc>
</p>
		
<h3>Embedded Value
			&mdash;
			Объединённое свойство</h3>
<img src="%0A%09%09%09%09img/embedded-value.gif%0A%09%09%09"><p>
<desc>
				
<p>Записывает объект в несколько полей таблицы другого объекта.
				</p>
				
<p>
					Множество небольших объектов играют важную роль в
					объектно-ориентированной системе, но не подходят для хранения в
					отдельной таблице. Это, к примеру, объекты-деньги, зависящие от
					валюты и диапазоны дат. Не смотря на то, что обычно для хранения
					отдельного объекта используется отдельная таблица, ни один человек
					в
					трезвом уме не станет делать отдельную таблицу для денег.
				</p>
				
<p>
					Паттерн Embedded Value (Объединённое свойство) распределяет значения полей
					объекта в поля таблицы объекта-владельца.
				</p>
				
<p>
					На схеме представлен объект "Место работы" (Employment) со ссылками
					на
					объекты диапазона дат и денег. В таблице, хранящей объект "место
					работы", объекты дат и денег раскладываются на отдельные поля, но не
					хранятся в отдельных таблицах.
				</p>
			
</desc>
</p>
		
<h3>Serialized LOB
			&mdash;
			Сериализованный LOB</h3>
<img src="%0A%09%09%09%09img/serialized-lob.gif%0A%09%09%09"><p>
<desc>
				
<p>Хранение графа связей объектов в БД посредством сериализации их
					в один large object (LOB).
				</p>
				
<p>
					Объектная модель зачастую содержит сложные графы взаимосвязей мелких
					объектов. Большая часть информации в таких структурах содержится не
					в самих объектах, а в связях между ними. Например, при работе со
					структурой организации, объектная модель достаточно хорошо может
					отразить все взаимосвязи между структурами и можно с лёгкостью
					добавлять методы, позволяющие получать данные об отделах и их
					взаимосвязях.
				</p>
				
<p>
					Но хранение этой структуры в БД - не такая уж и простая задача.
					Первое
					приходящее на ум решение - таблица "организация" с внешним ключём к
					родителю. Но работа с такой структурой БД требует использования
					JOIN'ов, которые одновременно медленные и громоздкие.
				</p>
				
<p>
					Объекты не нуждаются в представлении в виде связанных записей в таблице.
					Есть другая форма представления - сериализация, когда весь граф
					объектов записывается в один LOB (large object).
				</p>
			
</desc>
</p>
		
<h3>Single Table Inheritance
			&mdash;
			Наследование с единой таблицей</h3>
<img src="%0A%09%09%09%09img/single-table-inheritance.gif%0A%09%09%09"><p>
<desc>
				
<p>Представление всех классов из иерархии наследования в виде
					одной таблицы в БД, содержащей столбцы для всех полей различных
					классов.
				</p>
				
<p>
					Реляционные БД не поддерживают наследование, по этому, записывая данные об
					объектах в БД, мы вынуждены придумывать, как отобразить
					наследование
					в таблицах. Конечно, мы стараемся минимизировать JOIN'ы, которые
					мнговенно появятся, если наследование реализовывать несколькими
					таблицами в БД. Паттерн Single Table Inheritance (наследование с
					единой таблицей) записывает все поля всех классов иерархии в одну
					таблицу.
				</p>
			
</desc>
</p>
		
<h3>Class Table Inheritance
			&mdash;
			Наследование с таблицами классов</h3>
<img src="%0A%09%09%09%09img/class-table-inheritance.gif%0A%09%09%09"><p>
<desc>
				
<p>Представляет иерархию наследования классов в виде структуры БД,
					когда одна таблица отвечает одному классу.
				</p>
				
<p>
					Одно из самых заметных несоответствий между объектной и реляционной
					моделью - отсутствие в РБД поддержки наследования. Иногда
					необходима
					структура БД, точно соответсвующая объектной модели и позволяющая
					наращивать дерево наследования. Паттерн Class Table Inheritance
					(Наследование с таблицами классов) предоставляет такие возможности,
					используя одну таблицу на один класс из структуры наследования.
				</p>
			
</desc>
</p>
		
<h3>Concrete Table Inheritance
			&mdash;
			Наследование с таблицами конечных классов</h3>
<img src="%0A%09%09%09%09img/concrete-table-inheritance.gif%0A%09%09%09"><p>
<desc>
				
<p>Представляет иерархию наследования классов в виде структуры БД,
					когда одна таблица отвечает целиком одному классу.
				</p>
				
<p>
					Проблема объектно-реляционного взаимодействия заключается в отсутствии
					поддержки наследования в РБД. Если рассматривать таблицы с
					объектной
					точки зрения, есть смысл записывать каждый объект в отдельную запись
					в БД. Такой подход реализует паттерн Concrete Table Inheritance, в
					котором каждому конкретному классу из иерархии наследования
					соответствует своя таблица.
				</p>
			
</desc>
</p>
		
<h3>Inherritance Mappers
			&mdash;
			Наследуемые распределители</h3>
<img src="%0A%09%09%09%09img/inheritance-mappers.gif%0A%09%09%09"><p>
<desc>
				
<p>Структура организации распределителей данных, которые работают
					с деревом наследования
				</p>
				
<p>
					При работе с распределением объектных данных из дерева наследования в
					БД, необходимо уменьшить объём кода, используемого для записи и
					чтения данных из БД. Также необходимо предоставлять и абстрактные,
					и
					конкретные методы распределения данных, которые позволяли бы
					сохранять и читать и родительские и дочерние классы.
				</p>
				
<p>
					Не смотря на то, что нюансы такого поведения могут видоизменяться в
					зависимости от схемы работы с деревом насделования ( Single Table
					Inheritance, Class Table Inheritance или Concrete Table
					Inheritance), общая струтура одинакова для них всех.
				</p>
			
</desc>
</p>
	
	
<h2>Паттерны логики сущности</h2>
		
<h3>Transaction Script
			&mdash;
			Сценнарий транзакции</h3>
<img src="%0A%09%09%09%09img/transaction-script.gif%0A%09%09%09"><p>
<desc>
				
<p>Организует бизнес-логику в процедуры, которые управляют каждая
					своим запросом.
				</p>
				
<p>
					Большинство бизнес-приложений можно представить в виде набора транзакций.
					Какие-то из них выбират данные, какие-то ‐ меняют. Каждое
					взаимодействие пользователя и системы содержит определённый набор
					действий. В некоторых случаях это может быть просто вывод данных из
					БД. В других случаях эти дествия могут содержать в себе множество
					вычислений и проверок.
				</p>
				
<p>
					Паттерн Transaction Script организует всю эту логику в одну процедуру,
					работая в БД напрямую или через тонкую обёртку. Каждая транзакция
					имеет свой Transaction Script, хотя общие подзадачи могкт быть
					разбиты на процедуры.

				</p>
			
</desc>
</p>
		
<h3>Domain Model
			&mdash;
			Модель области определения</h3>
<img src="%0A%09%09%09%09img/domain-model.gif%0A%09%09%09"><p>
<desc>
				
<p>Объектная модель домена, объединяющая данные и поведение.
				</p>
				
<p>
					К сожалению, бизнес-логика приложения может быть очень сложной.
					Правила и логика описывают множество случаев и модификаций
					поведения. Для обработки всей этой сложной логики и проектируются
					объекты. Паттерн Domain Model (модель области определения) образует
					сеть взаимосвязанных объектов, в которой каждый объект представляет
					собой отдельную значащую сущность: может быть настолько большую,
					как
					корпорация или настолько малую, как строка из формы заказа.

				</p>
			
</desc>
</p>
		
<h3>Table Module
			&mdash;
			Обработчик таблицы</h3>
<img src="%0A%09%09%09%09img/table-module.gif%0A%09%09%09"><p>
<desc>
				
<p>Одна сущность обрабатывает всю бизнес-логику для всех строк
					таблице БД или виде.
				</p>
				
<p>
					Один из основополагающих принципов в ООП - сочетание данных и методов
					обработки этих данных. Традиционный объектно-ориентированный подход
					основан на объектах с соответствием, как, например, в паттерне
					Domain Model. Таким образом, если есть класс Employee, люой
					экземпляр этого класса соответствует конкретному работнику. Эта
					структура работает хорошо, потому что, имея связь, можно выполнять
					операции, использователь отношения, и собирать данные о работнике
				</p>
				
<p>
					Одна из проблем в паттерне Domain Model заключается в интерфейсе к
					БД. Этот подход относится к БД, как к сумашедшей тётушке, запертой
					на чердаке, с которой никто не хочет говорить. Частенько, приходится
					сильно постараться, чтобы записать или считать данные из БД,
					преобразуя их между двумя представлениями.
				</p>
				
<p>
					Паттерн Table Module разделяет логику области определения (домена) на
					отдельные классы для каждой таблицы в БД и один экземпляр класса
					содержит различные процедуры, работающие с данными. Основное
					отличие
					от Domain Model заключается в том, что если есть несколько заказов,
					то Domain Model будет создавать для каждого из заказов свой объект,
					а Table Module будет управлять всем заказами при помощи одного
					объекта.
				</p>
			
</desc>
</p>
		
<h3>Service Layer
			&mdash;
			Сервисный уровень</h3>
<img src="%0A%09%09%09%09img/service-layer.gif%0A%09%09%09"><p>
<desc>
				
<p>Определяет границу между приложением и слоем сервисов, который
					образует набор доступных операций и управляет ответом приложения в
					каждой операции.
				</p>
				
<p>
					Бизнес-приложения обычно нуждаются в различных интерфейсах к данным, которые они
					хранят и логике, которую реализуют: загрузчики данных,
					пользовательские интерфейсы, интеграционные шлюзы и другое. Вопреки
					различным целям, эти интерфейсы часто нуждаются во взаимодействии с
					приложением для доступа и управления его данными и исполнения
					логики. Эти взаимодействия могут быть сложными, использующими
					транзакции на нескольких ресурсах и управление несколькими ответами
					на действие. Программирование логики взаимодействия для каждого
					интерфейса вызовет больше количество дублирования.
				</p>
				
<p>
					Паттерн Service Layer определяет для приложения границу и набор допустимых
					операций с точки зрения взаимодействующих с ним клиентских. Он
					инкапсулирует бизнес-логику приложения, управляя транзакциями и
					управляя ответами в реализации этих операций.
				</p>
			
</desc>
</p>
	
	
<h2>Паттерны обработки Объектно-Реляционных метаданных</h2>
		
<h3>Metadata Mapping
			&mdash;
			Распределение на основе метаданных</h3>
<img src="%0A%09%09%09%09img/metadata-mapping.gif%0A%09%09%09"><p>
<desc>
				
<p>Хранит данные об объектно-реляционном распределении в
					метаданных
				</p>
				
<p>
					В большинстве случаев, код, управляющий объектно-реляционным
					распределением описывает, как поля в БД соотносятся с полями в
					объектах. Такой код получается сильно повторяющимся и скучным.
					Паттерн Metadata Mapping позволяет разработчикам определять правила
					распределения (маппинга) в простой табличной форме, которая может
					быть обработана общим кодом, который получает данные о правилах
					записи и чтения данных из БД.
				</p>
			
</desc>
</p>
		
<h3>Query Object
			&mdash;
			Объект-запрос</h3>
<img src="%0A%09%09%09%09img/query-object.gif%0A%09%09%09"><p>
<desc>
				
<p>Объект, представляющий запрос к БД
				</p>
				
<p>
					SQL зачастую сопряженно используемый язык и многие разработчики не
					совсем хорошо в нём разбираются. Более того, необходимо знать, как
					выглядит структура базы данных, чтобы создавать запросы. Можно
					избежать этого, создав специальные методы поиска, которые сожержат
					в
					себе весь SQL и управляются ограниченным набором параметров. Такой
					подход делает сложным создание и тюнинг запросов для конкретных
					ситуаций. Также это ведёт к дублированию в SQL-выражениях.
				</p>
				
<p>
					Паттерн Query Object - это структура объектов, которая может
					интерпретироваться в SQL-запрос. Можно создавать такой запрос
					ссылаясь на классы и поля так же как на таблицы и столбцы. Таким
					образом создаётся независимость разработчика от струткуры БД и
					конкретной реализации БД.
				</p>
			
</desc>
</p>
		
<h3>Repository
			&mdash;
			Репозиторий</h3>
<img src="%0A%09%09%09%09img/repository.gif%0A%09%09%09"><p>
<desc>
				
<p>Посредничает между уровнями области определения и распределения
					данных (domain and data mapping layers), используя интерфейс,
					схожий
					с коллекциями для доступа к объектам области определения.
				</p>
				
<p>
					Система со сложной моделью области определения может быть упрощена при
					помощи дополнительного уровня, например Data Mapper, который бы
					изолировал объекты от кода доступа к БД. В таких системах может
					быть
					полезным добавление ещё одного слоя абстракции поверх слоя
					распределения данных (Data Mapper), в котором бы был собран код
					создания запросов. Это становится ещё более важным, когда в области
					определения множество классов или при сложных, тяжелых запросах. В
					таких случаях добавление этого уровня особенно помогает сократить
					дублирование кода запросов.
				</p>
				
<p>
					Паттерн Repository посредничает между слоем области определения и слоем
					распределения данных, работая, как обычная колекция объектов
					области
					определения. Объекты-клиенты создают описание запроса декларативно и
					направляют их к объекту-репозиторию (Repository) для обработки.
					Объекты могут быть добавлены или удалены из репозитория, как будто
					они формируют простую коллекцию объектов. А код распределения
					данных, скрытый в объекте Repository, позаботится о соответсвующих
					операциях в незаметно для разработчика. В двух словах, паттерн
					Repository инкапсулирует объекты, представленыые в хранилище данных
					и операции, производимые над ними, предоставляя более
					объектно-ориентированное представление реальных данных. Repository
					также преследует цель достижения полного разделения и односторонней
					зависимости между уровнями области определения и распределения
					данных.
				</p>
			
</desc>
</p>
	
	
<h2>Паттерны распределения данных</h2>
		
<h3>Remote Facade
			&mdash;
			Парадный вход</h3>
<img src="%0A%09%09%09%09img/remote-facade.gif%0A%09%09%09"><p>
<desc>
				
<p>Предоставляет общий объединяющий интерфейс для набора методов
					объекта для улучшения эффективности сетевого взаимодействия.
				</p>
				
<p>
					Паттерн Remote Facade в объектно-ориентированной модели улучшает работу с
					маленькими объектами, у которых маленькие методы. Маленькие методы
					открывают большие возможности для контроля и изменения поведения, а
					также для улучшения понимания клиентом работы приложения. Одно из
					последствий такого "мелко-молотого" поведения в том, что обычно
					происходит много взаимодействий между объектами с вызовом множества
					методов.
				</p>
				
<p>
					В одном адресном пространстве "мелко-молотые" взаимодействия работаю
					хорошо, но всё меняется, когда происходит взаимодействие между
					процессами. Удалённые вызовы более затратны, потому что многое надо
					сделать: иногда данные нужно упорядочить, проверить на
					безопасность,
					пакеты должны быть маршрутизированы на свичах. Если два процесса
					работают на разных краях света, даже скорость света может играть
					роль. Тяжелая правда в том, что любые межпроцессные взаимодействия
					на порядок более расточительны, чем анутрипроцессные вызовы. Даже,
					если оба процесса работают на одной машине. Такое влияние на
					производительность не может быть упущено из вида, даже
					приверженцами
					ленивой оптимизации.
				</p>
				
<p>
					В результате любой объект, который задействован в удалённом
					взаимодействии, нуждается в более общем интерфейсе, который бы
					позволил минимизировать количество запросов, необходимых, чтобы
					сделать что-либо. Это затрагивает не только методы, но и объекты.
					Вместо того, чтобы запрашивать счёт и все его пункты отдельно, надо
					считать и обновить все пункты счёта за одно обращение. Это влияет
					на
					всю структуру объекта. Надо забыть о благой цели малых объектов и
					малых методов. Программирование становится всё сложнее,
					продуктивность падает и падает.
				</p>
				
<p>
					Паттерн Remote Facade представляет собой общий "Фасад" (по GoF) поверх
					структуры более "мелко-молотых" объектов. Ни один из этих объектов
					не имеет удалённого интерфейса, а Remote Facade не включает в себя
					никакой бизнес-логики. Всё, что делает Remote Facade - это
					транслирует общие запросы в набор небольших запросов к подчинённым
					объектам.
				</p>
			
</desc>
</p>
		
<h3>Data Transfer Object
			&mdash;
			Объект передачи данных</h3>
<img src="%0A%09%09%09%09img/data-transfer-object.gif%0A%09%09%09"><p>
<desc>
				
<p>Объект, которыей пересылает данные между процессами для
					уменьшения количества вызовов методов.
				</p>
				
<p>
					При работе с удалённым интерфейсом, таким как, например, Remote
					Facade,
					каждый запрос к нему достаточно затратен. В результате, приходится
					уменьшать количество вызовов, что означает необходимость передачи
					большего количества данных за один вызов. Чтобы реализовать это,
					как
					вариант, можно использовать множество прааметров. Однако, при этом
					зачастую код получается неуклюжим и неудобным. Также это часто
					невозможно в таких языках, как Java, которые возвращают лишь одно
					значение.
				</p>
				
<p>
					Решением здесь является паттерн Data Transfer Object, который может хранить
					всю необходимую для вызова информацию. Он должен быть сериализуемым
					для удобной передачи по сети. Обычно используется объект-сборщик
					для
					передачи данных между DTO и объектами в приложении.
				</p>
				
<p>
					В сообществе Sun многие используют термин "Value Object" для
					обозначения этого паттерна. Мартин Фаулер подразумевает под этим
					термином ( Value Object ) несколько иной паттерн. Обсуждение этого
					можно прочесть в его книге P of EEA на странице 487.
				</p>
			
</desc>
</p>
	
	
<h2>Паттерны локальной конкуренции</h2>
		
<h3>Optimistic offline Lock
			&mdash;
			Оптимистичная блокировка</h3>
<img src="%0A%09%09%09%09img/optimistic-offline-lock.gif%0A%09%09%09"><p>
<desc>
				
<p>Предотвращает конфликты между конкурирующими
					бизнес-транзакциями, выявляя их и откатывая транзакцию назад.
				</p>
				
<p>
					Зачастую бизнес-транзакция подразумевает выполнение нескольких
					системных транзакций. Выходя за пределы одиночной системной
					транзакции, мы не можем полагаться только на систему управления БД,
					чтобы быть уверенными в том, что бизнес-транзакция оставит данные в
					консистентном состоянии. Целостность данных находится под угрозой,
					каждый раз, когда две бизнес-транзакции начинают работу над одними
					и
					теми же данными. Также может случиться ситуация, когда один процесс
					читает данные в то время, как другой - обновляет.
				</p>
				
<p>
					Паттерн Optimistic Offline Lock решает эту проблему, проверяя
					завершённость
					одной транзакции и отсутствие конфликтов с другой. Успешная
					pre-commit проверка, в известном смысле, получает сигнал блокировки,
					что можно продолжать работать с изменениями в данных. Так как
					проверка происходит во время завершения каждой системной транзакции,
					бизнес-транзакции будут также консистентны.
				</p>
				
<p>
					Тогда как Pessimistic Offline Lock подразумевает, что шанс сессии на
					конфликт высок и по этому ограничивает системную конкуренцию,
					Optimistic Offline Lock подразумевает, что шансы на конфликт не
					велики. Такое предположение не очень подходит для одновременной
					работы нескольких пользователей над одними данными.

				</p>
			
</desc>
</p>
		
<h3>Pessimistic offline Lock
			&mdash;
			Пессимистичная блокировка</h3>
<img src="%0A%09%09%09%09img/pessimistic-offline-lock.gif%0A%09%09%09"><p>
<desc>
				
<p>Предотвращает конфликты между конкурирующими
					бизнес-транзакциями, разрешая доступ к одинм данным только одной
					бизнес-транзакции за раз.
				</p>
				
<p>
					Так как локальная конкуренция включает в себя работу с данными
					бизнес-транзакции, которая содержит несколько запросов, то наиболее
					простой подход был бы держать транзакцию открытой на протяжении
					всей
					бизнес-транзакции. Но, к сожалению, этот подход не всегда работает
					хорошо, потому что системы управления транзакциями не заточены под
					работу с длинными транзацкиями. По этому приходится делать несколько
					системных транзакций, а остальную конкуренцию отслеживать
					самостоятельно.
				</p>
				
<p>
					Первый из подходов, который следует попробовать в этом случае -
					Optimistic
					Offline Lock. Однако, этот паттерн имеет свои недостатки. Например,
					если несколько людей пытаются получить доступ к одним данным в одной
					бизнес-транзакции, один из них легко сможет сделать commit, но
					остальные получат конфликт и не смогут продолжить работу. Из-за
					того, что конфликты определяются только в конце бизнес-транзакции
					(а
					не предотвращаются), жертвы будут делать все действия тразакции и в
					последний момент обнаружат, что вся их работа псу под хвост. Если
					так будет происходить, системы с длинными транзакциями вскоре
					станут
					непопулярны.
				</p>
				
<p>
					Pessimistic Offline Lock предотвращает конфликты, исключая их вообще. Этот
					паттерн заставляет бизнес-транзакцию накладывать блокировку на ту
					часть данных, с которыми она работает, так что чтобы начать работу
					с
					данными другой пользователь сначала ждёт, пока данные освободятся.
				</p>
			
</desc>
</p>
		
<h3>Coarse Grained Lock
			&mdash;
			Грубая блокировка</h3>
<img src="%0A%09%09%09%09img/coarse-grained-lock.gif%0A%09%09%09"><p>
<desc>
				
<p>Блокирует набор связанных объектов при помощи одной блокировки.
				</p>
				
<p>
					Объекты часто могут отредактироваться в группе. Например, есть
					клиент и набор его адресов. В таком случае можно блокировать их все,
					если надо обратиться к одному из них. Блокировка их по отдельности
					приведёт к множеству проблем. Во-первых все кто пытается работать с
					такими данными, будет вынужден создавать код для поиска всех
					записей, чтобы потом заблокировать их. Это достаточно просто в
					примере с клиентом и адресами, но что, если группа будет более
					сложной или групп будет больше. Куда поместить часть программной
					логики, которая отвечает за слияние блокировок. Если в стратегию
					блокировки входит правило, в соответствии с которым объект должен
					быть загружен перед блокировкой, как например в Optimistic Offline
					Lock , то блокировка большого массива объектов вызовет провал в
					производительности. А в случае с Pessimistic Offline Lock , большая
					блокировка вызовет проблемы с управлением и увеличит конкуренцию за
					блокировки.
				</p>
				
<p>
					Паттерн Coarse-Grained Lock представляет собой одиночную блокировку,
					которая покрывает множество объектов. Она не только упрощает работу
					с блокировками, но ещё и освобождает разработчика от необходимости
					загружать все элементы группы, чтобы заблокировать их.
				</p>
			
</desc>
</p>
		
<h3>Implicit Lock
			&mdash;
			Скрытая блокировка</h3>
<img src="%0A%09%09%09%09img/implicit-lock.gif%0A%09%09%09"><p>
<desc>
				
<p>Позволяет коду фреймворка или супертипа уровня использовать
					локальные блокировки
				</p>
				
<p>
					Суть всех блокировок в том, что при их использовании нельзя делать
					исключений. Если забыть написать одну строку кода, которая вызывает
					блокировку, можно придти к полной бесполезности всей блокировочной
					схемы. Не вызвав блокировку на чтение, даже если остальные
					транзакции её используют, можно поставить под вопрос актуальность
					данных. В целом - если что-то может быть заблокировано где-то, оно
					должно блокироваться везде. Игнорируя это правило, блокировочные
					стратегии приложений рискуют целостностью данных. Если не завершить
					блокировку вовремя, то с данными ничего плохого не случится,
					однако,
					это приведёт к провалу производительности. Из-за сложности
					тестирования локальных блокировок, такие ошибки могут пройти все
					тесты и не быть обнаруженными
				</p>
				
<p>
					Единственное решение здесь - не дать разработчикам ошибиться. Задачи,
					использующие блокировки, которые не могут быть невыявленными,
					должны
					быть обработаны не явно для разработчика, но скрыто для приложения.
					А тот факт, что большинство приложений промышленного масштаба
					используют нектотрый набор фреймворков, Layer Supertype и генерацию
					кода, даёт большие возможности для внедрения паттерна Implicit
					Lock.
				</p>
			
</desc>
</p>
	

</section>
</body>
</html>
